/*
 * @Description: 地图导出插件
 * @Author: cgt
 * @Date: 2021-12-10 11:29:17
 * @LastEditors: cgt
 * @LastEditTime: 2021-12-28 19:43:52
 */
import { fabric } from 'fabric';
import { jsPDF as JsPDF } from 'jspdf';
import { saveAs } from 'file-saver';

import ITool from '../ITool';

/**
 * 地图导出插件
 * @implements {ITool}
 */
export default class ExportTool extends ITool {
  constructor(_top, _impl) {
    super(_top, _impl);
    this.name = 'ExportTool';
    this.desc = '地图导出插件';
    this.option = {
      pageSizeValue: '',
      dpiType: '',
      formatType: '',
      unit: ''
    };
    this.Format = {
      JPEG: 'jpg',
      PNG: 'png',
      PDF: 'pdf',
      SVG: 'svg'
    };
    this.Unit = {
      // don't use inch unit. because page size setting is using mm unit.
      in: 'in',
      mm: 'mm'
    };
    this.Size = {

      // A0, A1, B0, B1 are not working well.
      // A0: [1189, 841],
      // A1: [841, 594],
      A2: [594, 420],
      A3: [420, 297],
      A4: [297, 210],
      A5: [210, 148],
      A6: [148, 105],
      // B0: [1414, 1000],
      // B1: [1000, 707],
      B2: [707, 500],
      B3: [500, 353],
      B4: [353, 250],
      B5: [250, 176],
      B6: [176, 125]
    };
    this.width = this.Size.A4[0];
    this.height = this.Size.A4[1];
    this.dpi = 300;
    this.format = this.Format.PNG.toString();
    this.unit = this.Unit.mm;
  }

  onAdd() {
    super.onAdd();
  }

  onRemove() {
    super.onRemove();
  }
  _setOption(option) {
    this.width = (option.size || this.Size.A4)[0];
    this.height = (option.size || this.Size.A4)[1];
    this.dpi = option.dpi || 300;
    this.format = option.format || this.Format.PNG.toString();
    this.unit = option.unit || this.Unit.mm;
  }

  export(option) {
    console.log('option', option);
    this._setOption(option);
    console.log(

      this.width,
      this.height,
      this.dpi,
      this.format,
      this.unit
    );
    // 设置dpi
    const actualPixelRatio = window.devicePixelRatio;
    Object.defineProperty(window, 'devicePixelRatio', {
      get() {
        return this.dpi / 96;
      }
    });

    const canvas = this.getMap().getCanvas();
    // 文件名称
    const fileName = `map.${this.format}`;
    switch (this.format) {
      case this.Format.PNG:
        this.toPNG(canvas, fileName);
        break;
      case this.Format.JPEG:
        this.toJPEG(canvas, fileName);
        break;
      case this.Format.PDF:
        this.toPDF(canvas, fileName);
        break;
      // case this.Format.SVG:
      //   this.toSVG(canvas, fileName);
      //   break;
      default:
        console.error(`Invalid file format: ${this.format}`);
        break;
    }
    // 还原dpi
    Object.defineProperty(window, 'devicePixelRatio', {
      get() {
        return actualPixelRatio;
      }
    });
  }

  /**
   * Convert canvas to PNG
   * @param canvas Canvas element
   * @param fileName file name
   */
  toPNG(canvas, fileName) {
    canvas.toBlob((blob) => {
      // @ts-ignore
      saveAs(blob, fileName);
    });
  }

  /**
   * Convert canvas to JPEG
   * @param canvas Canvas element
   * @param fileName file name
   */
  toJPEG(canvas, fileName) {
    const uri = canvas.toDataURL('image/jpeg', 0.85);
    // @ts-ignore
    if (canvas.msToBlob) {
      // for IE11
      const blob = this.toBlob(uri);
      window.navigator.msSaveBlob(blob, fileName);
    } else {
      // for other browsers except IE11
      const a = document.createElement('a');
      a.href = uri;
      a.download = fileName;
      a.click();
      a.remove();
    }
  }

  /**
   * Convert Map object to PDF
   * @param map mapboxgl.Map object
   * @param fileName file name
   */
  toPDF(canvas, fileName) {
    var contentWidth = canvas.width;
    var contentHeight = canvas.height;
    //一页pdf显示html页面生成的canvas高度;
    var pageHeight = contentWidth / this.width * this.height;
    //未生成pdf的html页面高度
    var leftHeight = contentHeight;
    //页面偏移
    var position = 0;
    //a4纸的尺寸[595.28,841.89]，html页面生成的canvas在pdf中图片的宽高
    var imgWidth = this.width;
    var imgHeight = this.width / contentWidth * contentHeight;
    var pageData = canvas.toDataURL('image/jpeg', 1.0);
    //注①
    // var pdf = new jsPDF("", "pt", "a4");
    const pdf = new JsPDF({
      orientation: 'l',
      unit: this.unit,
      compress: false
    });
    //有两个高度需要区分，一个是html页面的实际高度，和生成pdf的页面高度(841.89)
    //当内容未超过pdf一页显示的范围，无需分页
    if(leftHeight < pageHeight) {
      pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
    } else {
      while(leftHeight > 0) {
        //arg3-->距离左边距;arg4-->距离上边距;arg5-->宽度;arg6-->高度
        pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);
        leftHeight -= pageHeight;
        position -= this.height; //避免添加空白页
        if(leftHeight > 0) {
          //注②
          pdf.addPage();
        }
      }
    }
    pdf.save(fileName);
    /*
    var w = this.width, h = this.width/canvas.width*canvas.height;
    const pdf = new jsPDF({
      orientation:"l",
      // unit: this.unit,
      compress: false,
    });
    console.log("pdf", pdf);
    pdf.addImage( canvas.toDataURL("image/jpeg", 1), "JPEG", 0, 0, w, h, undefined, "NONE");

    pdf.setProperties({
      title: fileName,
      creator: "askmewhat",
      author: "EPGIS FZCP",
    });

    pdf.save(fileName);
      */
  }

  /**
   * Convert canvas to SVG
   * this SVG export is using fabric.js. It is under experiment.
   * Please also see their document.
   * http://fabricjs.com/docs/
   * @param canvas Canvas element
   * @param fileName file name
   */
  toSVG(canvas, fileName) {
    const uri = canvas.toDataURL('image/png');
    fabric.Image.fromURL(uri, (image) => {
      const tmpCanvas = new fabric.Canvas('canvas');
      const pxWidth = Number(this.toPixels(this.width, this.dpi).replace('px', ''));
      const pxHeight = Number(this.toPixels(this.height, this.dpi).replace('px', ''));
      image.scaleToWidth(pxWidth);
      image.scaleToHeight(pxHeight);

      tmpCanvas.add(image);
      const svg = tmpCanvas.toSVG({
        // @ts-ignore
        x: 0,
        y: 0,
        width: pxWidth,
        height: pxHeight,
        viewBox: {
          x: 0,
          y: 0,
          width: pxWidth,
          height: pxHeight
        }
      });
      const a = document.createElement('a');
      a.href = `data:application/xml,${encodeURIComponent(svg)}`;
      a.download = fileName;
      a.click();
      a.remove();
    });
  }

  /**
   * Convert mm/inch to pixel
   * @param length mm/inch length
   * @param conversionFactor DPI value. default is 96.
   */
  toPixels(length, conversionFactor = 96) {
    var _conversionFactor = conversionFactor;
    if (this.unit === this.Unit.mm) {
      _conversionFactor /= 25.4;
    }
    return `${_conversionFactor * length}px`;
  }

  /**
   * Convert base64 to Blob
   * @param base64 string value for base64
   */
  toBlob(base64) {
    const bin = atob(base64.replace(/^.*,/, ''));
    const buffer = new Uint8Array(bin.length);
    for (let i = 0; i < bin.length; i += 1) {
      buffer[i] = bin.charCodeAt(i);
    }
    const blob = new Blob([buffer.buffer], { type: 'image/png' });
    return blob;
  }
  tomm(pixel) {
    return pixel * 25.4 / this.dpi;
  }
}
